package indi.simple.pms.util;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * 类
 *
 * @author wanglunhui
 * @since 2022-05-19 11:36:43
 */
//@Component
public class FtpUtil implements InitializingBean,DisposableBean {

    private FTPClient ftpClient;
    private final MODE mode= MODE.Passive;
    private final static String host="";// localhost
    private final static int port=21;
    private final static String username="";// username
    private final static String password="";// passeord
    private final static int timeout=60000;

    @Override
    public void afterPropertiesSet() throws Exception {
        this.ftpClient = new FTPClient();
        ftpClient.setControlEncoding(StandardCharsets.UTF_8.name());
        ftpClient.setConnectTimeout(timeout);

        try {
            ftpClient.connect(host,port);
            ftpClient.setSoTimeout(timeout);
            ftpClient.login(username,password);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        int replyCode = ftpClient.getReplyCode();
        if (!FTPReply.isPositiveCompletion(replyCode)) {
            try {
                ftpClient.disconnect();
            } catch (IOException e) {
            }

            throw new RuntimeException("Login failed for user " + username + " reply code is: " + replyCode);
        } else {
            switch(mode) {
                case Active:
                    this.ftpClient.enterLocalActiveMode();
                    break;
                case Passive:
                    this.ftpClient.enterLocalPassiveMode();
                    break;
                default:
                    throw new RuntimeException("unknown mode: " + mode);
            }
        }
    }

    @Override
    public void destroy() throws Exception {
        if (this.ftpClient!=null) {
            this.ftpClient.logout();
            if (this.ftpClient.isConnected()) {
                this.ftpClient.disconnect();
            }

            this.ftpClient = null;
        }
    }

    public boolean cd(String directory) {
        try {
            return this.ftpClient.changeWorkingDirectory(directory);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public String pwd() {
        try {
            return this.ftpClient.printWorkingDirectory();
        } catch (IOException var2) {
            throw new RuntimeException(var2);
        }
    }

    public List<FTPFile> ls(String path) {
        FTPFile[] ftpFiles;
        try {
            ftpFiles = this.ftpClient.listFiles(path);
        } catch (IOException var8) {
            throw new RuntimeException(var8);
        }

        if (ftpFiles==null||ftpFiles.length==0) {
            return Collections.emptyList();
        } else {
            return Arrays.asList(ftpFiles);
        }
    }

    public boolean mkdir(String dir) {
        try {
            return this.ftpClient.makeDirectory(dir);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public boolean deleteFile(String path) {
        boolean success;
        try {
            success = this.ftpClient.deleteFile(path);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return success;
    }

    public boolean deleteDirectory(String path) {
        if(path.charAt(path.length()-1)=='/'){ // 下面拼接/，所以这里要去掉
            path=path.substring(0,path.length()-1);
        }

        FTPFile[] ftpFiles;
        try {
            ftpFiles = this.ftpClient.listFiles(path);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        // 先删除文件
        for (FTPFile ftpFile:ftpFiles){
            String newPath=path+"/"+ftpFile.getName();
            if(ftpFile.isFile()){
                this.deleteFile(newPath);
            }else if(ftpFile.isDirectory()){
                // 递归删除目录
                this.deleteDirectory(newPath);
            }
        }

        // 最后删除自身
        try {
            return this.ftpClient.removeDirectory(path);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public boolean upload(String path, InputStream fileStream) {
        boolean success;
        try {
            this.ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            success = this.ftpClient.storeFile(path, fileStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return success;
    }

    public void download(String path, OutputStream out) {
        try {
            this.ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            this.ftpClient.retrieveFile(path, out);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    public FTPClient getFTPClient() {
        return this.ftpClient;
    }

    public enum MODE{
        Active,
        Passive;
    }
    
}
